11070. Хорошие старые времена
Имеется строка из не более 255 символов, содержащая
действительные числа и знаки арифметических операций (+, -, *, /). Необходимо
вычислить значение выражения, заданного в строке.
Вход. Каждая
строка содержит арифметическое выражение. Операции ‘+’ и ‘-‘ могут быть как бинарными, так и
унарными. Строка не содержит пробелов, табуляций и скобок.
Выход. Для каждого выражения вывести
его значение с тремя точками после запятой. 
1/2/2
-3.0
3
4.0+3.0/5.0
1*2*3+1+1*2+1*2*3*4
0.250
-3.000
3.000
4.600
33.000
синтаксический анализ
Для решения задачи следует
произвести интерпретацию входного выражения. Запишем грамматику для вычисления арифметического
выражения:
S ®  S + T | S - T | T
T ®  T * F | T / F | F
F ® +F | -F | G
G ®
<действительное число>
Преобразуем грамматику в не леворекурсивную
(e – пустое слово):
S  ® TS1
S1 ®  +TS1 | -TS1 | e
T  ® FT1
T1 ®  *FT1 | /FT1 | e
F  ® +F | -F | G 
G  ® <действительное число>
char stroka[256];
stack<double> Stack;
int len, ptr;
double a, b;
Каждому нетерминальному символу
не леворекурсивной грамматики поставим в соответствие процедуру. Каждое правило
грамматики выпишем отдельной процедурой. Выпишем объявления процедур, так как
они взаимно вызывают друг друга.
void s1(void);
void t1(void);void t(void);
void f(void);
void g(void);
void s(void)
{
  t(); s1();
}
void s1(void)
{
  if
(stroka[ptr] == '+')
  {
    ptr++; t(); 
    a = Stack.top(); Stack.pop();
    b = Stack.top(); Stack.pop();
    Stack.push(a+b);
    s1();
  }
  if
(stroka[ptr] == '-')
  {
    ptr++; t();
    a = Stack.top(); Stack.pop();
    b = Stack.top(); Stack.pop();
    Stack.push(b-a);
    s1();
  }
}
void t(void)
{
  f(); t1();
}
void t1(void)
{
  if
(stroka[ptr] == '*')
  {
    ptr++; f();
    a = Stack.top(); Stack.pop();
    b = Stack.top(); Stack.pop();
    Stack.push(a*b); 
    t1();
  }
  if
(stroka[ptr] == '/')
  {
    ptr++; f();
    a = Stack.top(); Stack.pop();
    b = Stack.top(); Stack.pop();
    Stack.push(b/a); 
    t1();
  }
}
void f(void)
{
  if
(stroka[ptr] == '+') 
  {
     ptr++; f();
  } else if (stroka[ptr] == '-')
  {
    ptr++; f();
    a = Stack.top(); Stack.pop();
    Stack.push(-a);
  } else g();
}
void g(void)
{
  double n;
  sscanf(stroka+ptr,"%lf",&n);
  Stack.push(n);
  while(isdigit(stroka[ptr])
|| (stroka[ptr] == '.')) ptr++;
}
Основная часть программы. Выражение
читаем в строку stroka, текущий указатель разбора выражения ptr
устанавливаем в 0. После вычисления выражения (вызова функции s) выводим
результат, который находится на вершине стека.
while(gets(stroka))
{
  ptr = 0; s();
  printf("%.3lf\n",Stack.top());
}